(function () {

    ClassPath.implement
    (
        {
            /**
             * Resolve the path to a class against this classpath
             * 
             * @param {String} canonicalName
             * @return {String} The path to the class
             */
            resolve: function (canonicalName) 
            {
                return this.classpath + canonicalName.replace(/\./g, '/') + '.js';
            }
            
            /**
             * @return {String}
             * @override
             */
        ,   toString: function () 
            {
                return this.classpath;
            }
        }
    );
    
    /**
     * A value object representing a class path
     * @param {String} classpath
     * @constructor
     */
    function ClassPath (classpath) 
    {
        if (!String.is(classpath)) 
            throw new TypeError ('Invalid classpath');

        if ('/' !== classpath.charAt(classpath.length-1))
            classpath+= '/';
            
        this.classpath= classpath;
    };

Runtime.declare("ie.ondevice.objectkit.utility.compiler.ClassPath",ClassPath);

})();
(function () {


    Loader.implement
    (
        {
            /**
             * Create a new network request object.
             * @return {XMLHttpRequest}
             */
            createNewRequest: new function () 
            {
                if (window.XMLHttpRequest) return function () 
                {
                    return new XMLHttpRequest;
                }
                
                if (window.ActiveXObject) return function () 
                {
                    return new ActiveXObject('MSXML2.XMLHTTP.3.0');
                }
                
                return function () 
                {
                    throw new Error('XMLHttpRequest is not supported');
                }
            }

            /**
             * Synchronously load a same domain resource.
             * 
             * @param {String} path The path to the resource to load
             * @return {String}    The contents of the loaded resources
             */
         ,  load: function (path) 
            {
                var xhr= this.createNewRequest()
                ,   status;
                
                xhr.open('GET', path, false);
                xhr.send(null);
                
                if (200 === xhr.status)
                    return xhr.responseText;
                    
                status= xhr.status + ':' + xhr.statusText;    
                    
                throw new Error('Could not load from path ' + path + ' - ' + status);
            }
        }
    );
    
    /**
     * A utility class to load same domain text resources.
     * @constructor
     */
    function Loader () {};

Runtime.declare("ie.ondevice.objectkit.utility.compiler.Loader",Loader);

})();
(function () {

    Annotation.implement
    (
        {
            /**
             * @private
             * @type {String}
             */
            name: null
            
            /**
             * @private
             * @type {String}
             */
        ,   value: null
            
            /**
             * @deprecated
             * @private
             * @type {ClassFile}
             */
        ,   declarer: null
            
            /**
             * @deprecated
             * @param {Object} value
             * @return {Boolean}
             */
        ,   equals: function (value) 
            {
                return Annotation.is(value) && this.name === value.name;
            }
            
            /**
             * @deprecated
             * @param {Object} value
             * @return {Boolean}
             */
        ,   isType: function (value) 
            {
                return this.name === value;
            }
            
            /**
             * @return {String}
             * @override
             */
        ,   toString: function () 
            {
                return this.name + ': ' + this.value + ';';
            }            
        }
    );
    
    /**
     * A value object representing an annotation declared in a source file.
     * @param {String} name
     * @param {String} value
     * @param {ClassFile} declarer
     * @constructor
     */
    function Annotation (name, value, declarer) 
    {
        this.name= name;
        this.value=value;
        this.declarer= declarer;
    };

Runtime.declare("ie.ondevice.objectkit.utility.compiler.Annotation",Annotation);

})();
(function () {

    CompilerListener.implement
    (
    
        {
            /**
             * A class has been loaded and its annotations parsed successfully, 
             * though its dependencies have not yet been analysed.
             * 
             * @param {ClassFile} classFile
             */
            onVisitClass: function (classFile) 
            {
               ;
            }
            
            /**
             * A class has finished being analysed and all its dependencies
             * are satisfied, and its been added to the compilers class list
             * 
             * @param {ClassFile} classFile
             */
        ,   onLeaveClass: function (classFile) 
            {
  
            }

            /**
             * The compiler has started.
             * 
             * @param {ClassFile} entryClassFile The entry class file
             */
        ,   onStart: function (entryClassFile) 
            {
               // console.log('Starting compiler with entryClass' + entryClassFile);
            }
            
            /**
             * The compiler has completed successfully.
             * 
             * @param {Array.<ClassFile>} classList the resolved classes in order
             * @return {void}
             */
        ,   onComplete: function (classFiles) 
            {
                //console.log('compiler complete.\n' + classFiles.join('\n'));
            }
            
            /**
             * The compiler has encountered an error while compiling the 
             * application, most likely due to a failed dependency.
             * 
             * @param {Object} classFile
             * @param {Object} cause
             */
        ,   onError: function (classFile, cause) 
            {
                console.log('onError: ' + classFile + ' - ' + cause);
                if (Error.is(cause))
                    throw cause;
            }
        }
    );
    
    function CompilerListener () {;};

Runtime.declare("ie.ondevice.objectkit.utility.compiler.CompilerListener",CompilerListener);

})();
(function () {

    ClassPath.implement
    (
        {
            /**
             * Resolve the path to a class against this classpath
             * 
             * @param {String} canonicalName
             * @return {String} The path to the class
             */
            resolve: function (canonicalName) 
            {
                return this.classpath + canonicalName.replace(/\./g, '/') + '.js';
            }
            
            /**
             * @return {String}
             * @override
             */
        ,   toString: function () 
            {
                return this.classpath;
            }
        }
    );
    
    /**
     * A value object representing a class path
     * @param {String} classpath
     * @constructor
     */
    function ClassPath (classpath) 
    {
        if (!String.is(classpath)) 
            throw new TypeError ('Invalid classpath');

        if ('/' !== classpath.charAt(classpath.length-1))
            classpath+= '/';
            
        this.classpath= classpath;
    };

Runtime.declare("ie.ondevice.objectkit.utility.compiler.ClassPath",ClassPath);

})();
(function () {


    Loader.implement
    (
        {
            /**
             * Create a new network request object.
             * @return {XMLHttpRequest}
             */
            createNewRequest: new function () 
            {
                if (window.XMLHttpRequest) return function () 
                {
                    return new XMLHttpRequest;
                }
                
                if (window.ActiveXObject) return function () 
                {
                    return new ActiveXObject('MSXML2.XMLHTTP.3.0');
                }
                
                return function () 
                {
                    throw new Error('XMLHttpRequest is not supported');
                }
            }

            /**
             * Synchronously load a same domain resource.
             * 
             * @param {String} path The path to the resource to load
             * @return {String}    The contents of the loaded resources
             */
         ,  load: function (path) 
            {
                var xhr= this.createNewRequest()
                ,   status;
                
                xhr.open('GET', path, false);
                xhr.send(null);
                
                if (200 === xhr.status)
                    return xhr.responseText;
                    
                status= xhr.status + ':' + xhr.statusText;    
                    
                throw new Error('Could not load from path ' + path + ' - ' + status);
            }
        }
    );
    
    /**
     * A utility class to load same domain text resources.
     * @constructor
     */
    function Loader () {};

Runtime.declare("ie.ondevice.objectkit.utility.compiler.Loader",Loader);

})();
(function () {

    Annotation.implement
    (
        {
            /**
             * @private
             * @type {String}
             */
            name: null
            
            /**
             * @private
             * @type {String}
             */
        ,   value: null
            
            /**
             * @deprecated
             * @private
             * @type {ClassFile}
             */
        ,   declarer: null
            
            /**
             * @deprecated
             * @param {Object} value
             * @return {Boolean}
             */
        ,   equals: function (value) 
            {
                return Annotation.is(value) && this.name === value.name;
            }
            
            /**
             * @deprecated
             * @param {Object} value
             * @return {Boolean}
             */
        ,   isType: function (value) 
            {
                return this.name === value;
            }
            
            /**
             * @return {String}
             * @override
             */
        ,   toString: function () 
            {
                return this.name + ': ' + this.value + ';';
            }            
        }
    );
    
    /**
     * A value object representing an annotation declared in a source file.
     * @param {String} name
     * @param {String} value
     * @param {ClassFile} declarer
     * @constructor
     */
    function Annotation (name, value, declarer) 
    {
        this.name= name;
        this.value=value;
        this.declarer= declarer;
    };

Runtime.declare("ie.ondevice.objectkit.utility.compiler.Annotation",Annotation);

})();
(function () {

    CompilerListener.implement
    (
    
        {
            /**
             * A class has been loaded and its annotations parsed successfully, 
             * though its dependencies have not yet been analysed.
             * 
             * @param {ClassFile} classFile
             */
            onVisitClass: function (classFile) 
            {
               ;
            }
            
            /**
             * A class has finished being analysed and all its dependencies
             * are satisfied, and its been added to the compilers class list
             * 
             * @param {ClassFile} classFile
             */
        ,   onLeaveClass: function (classFile) 
            {
  
            }

            /**
             * The compiler has started.
             * 
             * @param {ClassFile} entryClassFile The entry class file
             */
        ,   onStart: function (entryClassFile) 
            {
               // console.log('Starting compiler with entryClass' + entryClassFile);
            }
            
            /**
             * The compiler has completed successfully.
             * 
             * @param {Array.<ClassFile>} classList the resolved classes in order
             * @return {void}
             */
        ,   onComplete: function (classFiles) 
            {
                //console.log('compiler complete.\n' + classFiles.join('\n'));
            }
            
            /**
             * The compiler has encountered an error while compiling the 
             * application, most likely due to a failed dependency.
             * 
             * @param {Object} classFile
             * @param {Object} cause
             */
        ,   onError: function (classFile, cause) 
            {
                console.log('onError: ' + classFile + ' - ' + cause);
                if (Error.is(cause))
                    throw cause;
            }
        }
    );
    
    function CompilerListener () {;};

Runtime.declare("ie.ondevice.objectkit.utility.compiler.CompilerListener",CompilerListener);

})();
(function () {
var Annotation=ie.ondevice.objectkit.utility.compiler.Annotation
,   ClassFile=ie.ondevice.objectkit.utility.compiler.ClassFile;

    use: 'ie.ondevice.objectkit.utility.compiler.Annotation';
    use: 'ie.ondevice.objectkit.utility.compiler.ClassFile';

    AnnotationParser.implement
    (
        {
            /**
             * @private
             * @type {RegExp}
             */
            pattern: /\s*([a-z]+): *('[\w_\/\.]+'|[\w_\/\.]+);/g   
            
            /**
             * Parse and return any annotations declared in a class file.
             * Annotations are not removed from the source code as an aid
             * to debugging. Closure compiler will remove them for you.
             * 
             * @param {ClassFile} classFile
             * @return {Object} A collection of annotations
             */
        ,   parseAnnotations: function (classFile) 
            {
                var annotations= {}
                ,   sourceCode= classFile.sourceCode
                ,   match
                ,   name
                ,   value
                ,   nextIndex
                ,   lastIndex
                
                while (match= this.pattern.exec(sourceCode)) 
                {
                    if (lastIndex === (nextIndex= this.pattern.lastIndex)) 
                    {
                        console.log('Exiting infinite exec loop.');
                        break;
                    }
                    
                    lastIndex= nextIndex;
                    
                    name= match[1];
                    value=match[2];
                    
                    if ('\'' === value.charAt(0))
                        value= value.substr(1, value.length-2);
                        
                    if ('undefined' === typeof annotations[name]) 
                    {
                        annotations[name]= [];
                    }

                    annotations[name].push(new Annotation(name, value, classFile));
                }
                
                return annotations;
            }
        }
    );
    
    /**
     * @constructor
     */
    function AnnotationParser () {;}

Runtime.declare("ie.ondevice.objectkit.utility.compiler.AnnotationParser",AnnotationParser);

})();
(function () {
var AnnotationParser=ie.ondevice.objectkit.utility.compiler.AnnotationParser;

    use: 'ie.ondevice.objectkit.utility.compiler.AnnotationParser';

    ClassFile.implement
    (
        {
            /**
             * @private
             * @type {Array}
             */
            annotations: null
            
            /**
             * @private
             * @type {Array}
             */
        ,   dependencies: null  
          
            /**
             * @type {String}
             */
        ,   path: null
        
            /**
             * @type {String}
             */
        ,   canonicalName: null
        
            /**
             * @type {String}
             */
        ,   localName: null
        
            /**
             * @type {String}
             */
        ,   namespace: null
        
            /**
             * 
             * @return {Object}
             */
        ,   getAnnotations: function () 
            {
                if (!this.annotations) 
                {
                    this.annotations= new AnnotationParser().parseAnnotations(this);
                }
                
                return this.annotations;
            }
            
            /**
             * Get annotations declared in this class file by their name.
             * 
             * @param {String} name    The annotation name
             * @return {Array.<Annotation>}    A collection of annotations
             * @throws {ReferenceError} If no annotations are declared
             */
        ,   getDeclaredAnnotations: function(name) 
            {
                var annotations= this.getAnnotations();
                if (name in annotations)
                    return annotations[name];
                    
                throw new ReferenceError("Undeclared annotation: " + name);
            }
            
            /**
             * Get a list of the classes that this class depends on. If no
             * dependencies are inferred, an empty array is returned.
             * 
             * @return {Array.<String>}    A list of class names
             */
        ,   getDependencies: function () 
            {
                if (this.dependencies)
                    return this.dependencies;
                
                var dependencies= []
                ,   annotations= this.getAnnotations()
                ,   annotation
                ,   annotations
                    
                if ('use' in annotations) 
                {
                    annotations= annotations['use'];
                    for (var i= 0, n= annotations.length; i<n; i++) 
                    {
                        annotation= annotations[i];
                        dependencies.push(annotation.value)    
                    }
                }

                return this.dependencies= dependencies;
            }
            
            /**
             * Get the file size.
             * @return {Number}
             */
        ,   getFileSize: function () 
            {
                return this.sourceCode.length;
            }
            
            /**
             * @return {String}
             * @override
             */
        ,   toString: function () 
            {
                return this.path;//this.canonicalName; // + ' - ' + this.path;
            }
        }
    );
    
    /**
     * A value object representing a class file.
     * 
     * @param {String} canonicalName
     * @param {String} path
     * @param {String} sourceCode
     * @constructor
     */
    function ClassFile (canonicalName, path, sourceCode) 
    {
        var namespace= canonicalName.split('.');
        this.canonicalName= canonicalName;
        this.localName= namespace.pop();
        this.namespace= namespace.join('.');
        this.path= path;
        this.sourceCode= sourceCode;
    };

Runtime.declare("ie.ondevice.objectkit.utility.compiler.ClassFile",ClassFile);

})();
(function () {
var Loader=ie.ondevice.objectkit.utility.compiler.Loader
,   ClassPath=ie.ondevice.objectkit.utility.compiler.ClassPath
,   ClassFile=ie.ondevice.objectkit.utility.compiler.ClassFile;

    use: 'ie.ondevice.objectkit.utility.compiler.Loader';
    use: 'ie.ondevice.objectkit.utility.compiler.ClassPath';
    use: 'ie.ondevice.objectkit.utility.compiler.ClassFile';
        
    ClassLoader.inherit(Loader).implement
    (
        {
            /**
             * Resolve a class file by a classes canonical name and load its
             * corresponding class file.
             * 
             * @param {String} canonicalName    The class name to load
             * @return {ClassFile}              The classes file
             * @throws {ClassLoaderError}       If the class file cannot be loaded
             * @override
             */
            load: function (canonicalName) 
            {
                var path= this.classpath.resolve(canonicalName)
                ,   sourceCode
                
                try 
                {
                    sourceCode= this.parent.load(path)
                }
                catch (thrown) 
                {
                    throw new Error ('Could not load class ' + canonicalName + '. ' + thrown.stack || thrown);
                }

                return new ClassFile (canonicalName, path, sourceCode);
            }
            
            /**
             * Set the classpath that the class loader will use to resolve
             * dependencies against.
             * @param {String} value
             */
        ,   setClasspath: function (value) 
            {
                this.classpath= new ClassPath(value);
            }
            
            /**
             * Get the classpath that the class loader is using to resolve
             * dependencies against.
             * @return {String}
             */
        ,   getClasspath: function () 
            {
                return String(this.classpath);
            }
        }
    );

    /**
     * 
     * @param {Classpath} classpath
     * @constructor
     * @extends {Loader}
     */
    function ClassLoader () 
    {
        this.setClasspath('/');
    };

Runtime.declare("ie.ondevice.objectkit.utility.compiler.ClassLoader",ClassLoader);

})();
(function () {
var ClassPath=ie.ondevice.objectkit.utility.compiler.ClassPath
,   ClassLoader=ie.ondevice.objectkit.utility.compiler.ClassLoader
,   CompilerListener=ie.ondevice.objectkit.utility.compiler.CompilerListener
,   ClassFile=ie.ondevice.objectkit.utility.compiler.ClassFile;

    use: 'ie.ondevice.objectkit.utility.compiler.ClassPath';
    use: 'ie.ondevice.objectkit.utility.compiler.ClassLoader';
    use: 'ie.ondevice.objectkit.utility.compiler.CompilerListener';
    use: 'ie.ondevice.objectkit.utility.compiler.ClassFile';

    Compiler.implement
    (
        {
            /**
             * @protected
             * A registry of classes used to track progress of dependency
             * resolution.
             * 
             * @type {Object}
             */
            classMap: null    
            
            /**
             * @protected
             * An ordered list representing the dependencies required to
             * support the entry class provided to #compile
             * @type {Array}
             * @see #compile
             * 
             * @type {Array}
             */
        ,   classList: null 

            /**
             * @private
             * 
             * @param {ClassFile} classFile
             * @return {void}
             */
        ,   visitClass: function (classFile) 
            {
                this.listener.onVisitClass(classFile);
                this.registerClass(classFile);
                this.analyse(classFile);
                this.leaveClass(classFile);
            }
            
            /**
             * Determine if a class has been registered by the compiler.
             * @param {String} canonicalName    A canonical class name
             * @return {Boolean}
             */
        ,   hasRegisteredClass: function (canonicalName) 
            {
                return canonicalName in this.classMap;
            }    
            
            /**
             * @private
             * 
             * Register a class with the compiler.
             * @param {ClassFile} classFile
             * @return {void}
             */
        ,   registerClass: function (classFile) 
            {
                this.classMap[classFile.canonicalName]= classFile;
            }
            
            /**
             * @private
             * A class has been fully inspected for dependencies and they have
             * all been satisfied.
             * 
             * @param {ClassFile} classFile
             * @return {void}
             */
        ,   leaveClass: function (classFile) 
            {
                this.classList.push(classFile);
                this.listener.onLeaveClass(classFile);
            }
            
            /**
             * 
             * @param {String} value
             */
        ,   setClasspath: function (value) 
            {
                this.classLoader.setClasspath(value);
            }
            
        ,   setListener: function (value) 
            {
                this.listener= value;
            }
            
            /**
             * 
             * @param {String} canonicalName
             * @throws {Error} if the class could not be loaded
             */
        ,   compile: function (canonicalName) 
            {
                try 
                {
                    var entryClass= this.classLoader.load(canonicalName);
                    this.listener.onStart(entryClass);
                    this.visitClass(entryClass);
                }
                catch (thrown) 
                {
                    this.listener.onError(canonicalName, thrown);
                }
                finally 
                {
                    this.listener.onComplete(this.classList);
                }
            }
            
            /**
             * 
             * @param {ClassFile} classFile
             * @throws {Error} if the class loader could not load a class file
             */
        ,   analyse: function (classFile) 
            {
                var dependencies= classFile.getDependencies()
                ,   file
                ,   name
                ,   i= 0
                ,   n= dependencies.length
                
                for (; i< n; i++) 
                {
                    name= dependencies[i];
                    if (false === this.hasRegisteredClass(name)) 
                    {
                        this.visitClass(this.classLoader.load(name));
                        /*
                        this.listener.onVisitClass(classFile);
                        this.registerClass(classFile);
                        this.analyse(classFile);
                        this.classList.push(classFile);
                        this.listener.onLeaveClass(classFile);
                        */
                    } 
                }
            }
        }
    );
    
    /**
     * 
     * @param {Object} options
     * @constructor
     */
    function Compiler (options) 
    {
        var listener= new CompilerListener
        ,   classLoader= new ClassLoader
        
        if (Object.is(options)) 
        {
            if (CompilerListener.is(options.listener))
            {
                listener= options.listener;
            }
            
            if (String.is(options.classpath))
            {
                classLoader.setClasspath(options.classpath);
            }
        };
        
        this.classLoader= classLoader;
        this.listener= listener;  
        this.classMap= {};
        this.classList= [];
    };

Runtime.declare("ie.ondevice.objectkit.utility.compiler.Compiler",Compiler);

})();
(function () {
var Compiler=ie.ondevice.objectkit.utility.compiler.Compiler;

    use: 'ie.ondevice.objectkit.utility.compiler.Compiler';

    AppLoader.inherit(Compiler).implement
    (
        {
            /**
             * 
             * @param {String} entryClass    A canonical class name.
             */
            load: function (entryClass) 
            {
                this.parent.compile.call(this, entryClass);
                
                var i= 0, n= this.classList.length
                ,   classFile
                ,   sourceCode
                ,   script
                ,   vars
                ,   dependencies
                ,   dependency
                ,   declaration
                ,   contents= ''
                
                
                for (; i < n; i++) 
                {
                    classFile= this.classList[i];
                    
                    dependencies= classFile.getDependencies()
                    
                    if (0 === dependencies.length) 
                    {
                        vars= '';
                    }
                    else 
                    {
                        vars= []
                        for (var j= 0, k= dependencies.length; j < k; j++) 
                        {
                            
                            dependency= dependencies[j];
                            dependency= this.classMap[dependency];
                            
                            if ('undefined' === typeof dependency)
                                throw new Error ('Undeclared class ' + dependency);
                                
                            vars.push(dependency.localName + '=' + dependency.canonicalName);
                        }
                        vars= 'var ' + vars.join('\n,    ') + ';';
                    }

                    contents+='\n////////////////////////////////////////////'
                    + '\n// ' + classFile.path
                    + '\n////////////////////////////////////////////'  
                    + '\n(function(){\n'
                    + vars
                    + classFile.sourceCode
                    + 'Runtime.declare("' + classFile.canonicalName + '", ' + classFile.localName + ');'
                    + '\n})();\n'
                    ;

                    
                    document.write('<script type="text/javascript">' + sourceCode + '<\/script>');
                }
                
                
            }
        }
    );
    
    /**
     * AppLoader is a development utility that first scans files for interdependencies
     * and then adds them to the dom by injecting script tags. The advantage of
     * doing this is that the browser should be able to reliably detect the
     * location of errors in individual files, prior to any compression that
     * may be performed before deployment to production servers.
     * 
     * @constructor
     * @extends {ie.ondevice.objectkit.utility.compiler.Compiler}
     */
    function AppLoader () 
    {
        Compiler.call(this);
    };

Runtime.declare("ie.ondevice.objectkit.utility.apploader.AppLoader",AppLoader);

})();
(function () {
var Annotation=ie.ondevice.objectkit.utility.compiler.Annotation
,   ClassFile=ie.ondevice.objectkit.utility.compiler.ClassFile;

    use: 'ie.ondevice.objectkit.utility.compiler.Annotation';
    use: 'ie.ondevice.objectkit.utility.compiler.ClassFile';

    AnnotationParser.implement
    (
        {
            /**
             * @private
             * @type {RegExp}
             */
            pattern: /\s*([a-z]+): *('[\w_\/\.]+'|[\w_\/\.]+);/g   
            
            /**
             * Parse and return any annotations declared in a class file.
             * Annotations are not removed from the source code as an aid
             * to debugging. Closure compiler will remove them for you.
             * 
             * @param {ClassFile} classFile
             * @return {Object} A collection of annotations
             */
        ,   parseAnnotations: function (classFile) 
            {
                var annotations= {}
                ,   sourceCode= classFile.sourceCode
                ,   match
                ,   name
                ,   value
                ,   nextIndex
                ,   lastIndex
                
                while (match= this.pattern.exec(sourceCode)) 
                {
                    if (lastIndex === (nextIndex= this.pattern.lastIndex)) 
                    {
                        console.log('Exiting infinite exec loop.');
                        break;
                    }
                    
                    lastIndex= nextIndex;
                    
                    name= match[1];
                    value=match[2];
                    
                    if ('\'' === value.charAt(0))
                        value= value.substr(1, value.length-2);
                        
                    if ('undefined' === typeof annotations[name]) 
                    {
                        annotations[name]= [];
                    }

                    annotations[name].push(new Annotation(name, value, classFile));
                }
                
                return annotations;
            }
        }
    );
    
    /**
     * @constructor
     */
    function AnnotationParser () {;}

Runtime.declare("ie.ondevice.objectkit.utility.compiler.AnnotationParser",AnnotationParser);

})();
(function () {
var AnnotationParser=ie.ondevice.objectkit.utility.compiler.AnnotationParser;

    use: 'ie.ondevice.objectkit.utility.compiler.AnnotationParser';

    ClassFile.implement
    (
        {
            /**
             * @private
             * @type {Array}
             */
            annotations: null
            
            /**
             * @private
             * @type {Array}
             */
        ,   dependencies: null  
          
            /**
             * @type {String}
             */
        ,   path: null
        
            /**
             * @type {String}
             */
        ,   canonicalName: null
        
            /**
             * @type {String}
             */
        ,   localName: null
        
            /**
             * @type {String}
             */
        ,   namespace: null
        
            /**
             * 
             * @return {Object}
             */
        ,   getAnnotations: function () 
            {
                if (!this.annotations) 
                {
                    this.annotations= new AnnotationParser().parseAnnotations(this);
                }
                
                return this.annotations;
            }
            
            /**
             * Get annotations declared in this class file by their name.
             * 
             * @param {String} name    The annotation name
             * @return {Array.<Annotation>}    A collection of annotations
             * @throws {ReferenceError} If no annotations are declared
             */
        ,   getDeclaredAnnotations: function(name) 
            {
                var annotations= this.getAnnotations();
                if (name in annotations)
                    return annotations[name];
                    
                throw new ReferenceError("Undeclared annotation: " + name);
            }
            
            /**
             * Get a list of the classes that this class depends on. If no
             * dependencies are inferred, an empty array is returned.
             * 
             * @return {Array.<String>}    A list of class names
             */
        ,   getDependencies: function () 
            {
                if (this.dependencies)
                    return this.dependencies;
                
                var dependencies= []
                ,   annotations= this.getAnnotations()
                ,   annotation
                ,   annotations
                    
                if ('use' in annotations) 
                {
                    annotations= annotations['use'];
                    for (var i= 0, n= annotations.length; i<n; i++) 
                    {
                        annotation= annotations[i];
                        dependencies.push(annotation.value)    
                    }
                }

                return this.dependencies= dependencies;
            }
            
            /**
             * Get the file size.
             * @return {Number}
             */
        ,   getFileSize: function () 
            {
                return this.sourceCode.length;
            }
            
            /**
             * @return {String}
             * @override
             */
        ,   toString: function () 
            {
                return this.path;//this.canonicalName; // + ' - ' + this.path;
            }
        }
    );
    
    /**
     * A value object representing a class file.
     * 
     * @param {String} canonicalName
     * @param {String} path
     * @param {String} sourceCode
     * @constructor
     */
    function ClassFile (canonicalName, path, sourceCode) 
    {
        var namespace= canonicalName.split('.');
        this.canonicalName= canonicalName;
        this.localName= namespace.pop();
        this.namespace= namespace.join('.');
        this.path= path;
        this.sourceCode= sourceCode;
    };

Runtime.declare("ie.ondevice.objectkit.utility.compiler.ClassFile",ClassFile);

})();
(function () {
var Loader=ie.ondevice.objectkit.utility.compiler.Loader
,   ClassPath=ie.ondevice.objectkit.utility.compiler.ClassPath
,   ClassFile=ie.ondevice.objectkit.utility.compiler.ClassFile;

    use: 'ie.ondevice.objectkit.utility.compiler.Loader';
    use: 'ie.ondevice.objectkit.utility.compiler.ClassPath';
    use: 'ie.ondevice.objectkit.utility.compiler.ClassFile';
        
    ClassLoader.inherit(Loader).implement
    (
        {
            /**
             * Resolve a class file by a classes canonical name and load its
             * corresponding class file.
             * 
             * @param {String} canonicalName    The class name to load
             * @return {ClassFile}              The classes file
             * @throws {ClassLoaderError}       If the class file cannot be loaded
             * @override
             */
            load: function (canonicalName) 
            {
                var path= this.classpath.resolve(canonicalName)
                ,   sourceCode
                
                try 
                {
                    sourceCode= this.parent.load(path)
                }
                catch (thrown) 
                {
                    throw new Error ('Could not load class ' + canonicalName + '. ' + thrown.stack || thrown);
                }

                return new ClassFile (canonicalName, path, sourceCode);
            }
            
            /**
             * Set the classpath that the class loader will use to resolve
             * dependencies against.
             * @param {String} value
             */
        ,   setClasspath: function (value) 
            {
                this.classpath= new ClassPath(value);
            }
            
            /**
             * Get the classpath that the class loader is using to resolve
             * dependencies against.
             * @return {String}
             */
        ,   getClasspath: function () 
            {
                return String(this.classpath);
            }
        }
    );

    /**
     * 
     * @param {Classpath} classpath
     * @constructor
     * @extends {Loader}
     */
    function ClassLoader () 
    {
        this.setClasspath('/');
    };

Runtime.declare("ie.ondevice.objectkit.utility.compiler.ClassLoader",ClassLoader);

})();
(function () {
var ClassPath=ie.ondevice.objectkit.utility.compiler.ClassPath
,   ClassLoader=ie.ondevice.objectkit.utility.compiler.ClassLoader
,   CompilerListener=ie.ondevice.objectkit.utility.compiler.CompilerListener
,   ClassFile=ie.ondevice.objectkit.utility.compiler.ClassFile;

    use: 'ie.ondevice.objectkit.utility.compiler.ClassPath';
    use: 'ie.ondevice.objectkit.utility.compiler.ClassLoader';
    use: 'ie.ondevice.objectkit.utility.compiler.CompilerListener';
    use: 'ie.ondevice.objectkit.utility.compiler.ClassFile';

    Compiler.implement
    (
        {
            /**
             * @protected
             * A registry of classes used to track progress of dependency
             * resolution.
             * 
             * @type {Object}
             */
            classMap: null    
            
            /**
             * @protected
             * An ordered list representing the dependencies required to
             * support the entry class provided to #compile
             * @type {Array}
             * @see #compile
             * 
             * @type {Array}
             */
        ,   classList: null 

            /**
             * @private
             * 
             * @param {ClassFile} classFile
             * @return {void}
             */
        ,   visitClass: function (classFile) 
            {
                this.listener.onVisitClass(classFile);
                this.registerClass(classFile);
                this.analyse(classFile);
                this.leaveClass(classFile);
            }
            
            /**
             * Determine if a class has been registered by the compiler.
             * @param {String} canonicalName    A canonical class name
             * @return {Boolean}
             */
        ,   hasRegisteredClass: function (canonicalName) 
            {
                return canonicalName in this.classMap;
            }    
            
            /**
             * @private
             * 
             * Register a class with the compiler.
             * @param {ClassFile} classFile
             * @return {void}
             */
        ,   registerClass: function (classFile) 
            {
                this.classMap[classFile.canonicalName]= classFile;
            }
            
            /**
             * @private
             * A class has been fully inspected for dependencies and they have
             * all been satisfied.
             * 
             * @param {ClassFile} classFile
             * @return {void}
             */
        ,   leaveClass: function (classFile) 
            {
                this.classList.push(classFile);
                this.listener.onLeaveClass(classFile);
            }
            
            /**
             * 
             * @param {String} value
             */
        ,   setClasspath: function (value) 
            {
                this.classLoader.setClasspath(value);
            }
            
        ,   setListener: function (value) 
            {
                this.listener= value;
            }
            
            /**
             * 
             * @param {String} canonicalName
             * @throws {Error} if the class could not be loaded
             */
        ,   compile: function (canonicalName) 
            {
                try 
                {
                    var entryClass= this.classLoader.load(canonicalName);
                    this.listener.onStart(entryClass);
                    this.visitClass(entryClass);
                }
                catch (thrown) 
                {
                    this.listener.onError(canonicalName, thrown);
                }
                finally 
                {
                    this.listener.onComplete(this.classList);
                }
            }
            
            /**
             * 
             * @param {ClassFile} classFile
             * @throws {Error} if the class loader could not load a class file
             */
        ,   analyse: function (classFile) 
            {
                var dependencies= classFile.getDependencies()
                ,   file
                ,   name
                ,   i= 0
                ,   n= dependencies.length
                
                for (; i< n; i++) 
                {
                    name= dependencies[i];
                    if (false === this.hasRegisteredClass(name)) 
                    {
                        this.visitClass(this.classLoader.load(name));
                        /*
                        this.listener.onVisitClass(classFile);
                        this.registerClass(classFile);
                        this.analyse(classFile);
                        this.classList.push(classFile);
                        this.listener.onLeaveClass(classFile);
                        */
                    } 
                }
            }
        }
    );
    
    /**
     * 
     * @param {Object} options
     * @constructor
     */
    function Compiler (options) 
    {
        var listener= new CompilerListener
        ,   classLoader= new ClassLoader
        
        if (Object.is(options)) 
        {
            if (CompilerListener.is(options.listener))
            {
                listener= options.listener;
            }
            
            if (String.is(options.classpath))
            {
                classLoader.setClasspath(options.classpath);
            }
        };
        
        this.classLoader= classLoader;
        this.listener= listener;  
        this.classMap= {};
        this.classList= [];
    };

Runtime.declare("ie.ondevice.objectkit.utility.compiler.Compiler",Compiler);

})();
(function () {
var Compiler=ie.ondevice.objectkit.utility.compiler.Compiler;

    use: 'ie.ondevice.objectkit.utility.compiler.Compiler';

    AppLoader.inherit(Compiler).implement
    (
        {
            /**
             * 
             * @param {String} entryClass    A canonical class name.
             */
            load: function (entryClass) 
            {
                this.parent.compile.call(this, entryClass);
                
                var i= 0, n= this.classList.length
                ,   classFile
                ,   sourceCode
                ,   script
                ,   vars
                ,   dependencies
                ,   dependency
                ,   declaration
                ,   contents= ''
                ,   head= document.getElementsByTagName('head').item(0)
                
                
                for (; i < n; i++) 
                {
                    classFile= this.classList[i];
                    
                    dependencies= classFile.getDependencies()
                    
                    if (0 === dependencies.length) 
                    {
                        vars= '';
                    }
                    else 
                    {
                        vars= []
                        for (var j= 0, k= dependencies.length; j < k; j++) 
                        {
                            
                            dependency= dependencies[j];
                            dependency= this.classMap[dependency];
                            
                            if ('undefined' === typeof dependency)
                                throw new Error ('Undeclared class ' + dependency);
                                
                            vars.push(dependency.localName + '=' + dependency.canonicalName);
                        }
                        vars= 'var ' + vars.join('\n,    ') + ';';
                    }

                    sourceCode='\n////////////////////////////////////////////'
                    + '\n// ' + classFile.path
                    + '\n////////////////////////////////////////////'  
                    + '\n(function(){\n'
                    + vars
                    + classFile.sourceCode
                    + 'Runtime.declare("' + classFile.canonicalName + '", ' + classFile.localName + ');'
                    + '\n})();\n'
                    ;
                    
                    contents+= sourceCode;

                    script= document.createElement('script');
                    script.setAttribute('type', 'text/javascript');
                    script.innerHTML= sourceCode;
                    try 
                    {
                        head.appendChild(script);
                    }
                    catch (thrown) 
                    {
                        throw 'Error in script ' + classFile;
                    }

                    //document.write('<script type="text/javascript">' + sourceCode + '<\/script>');
                }
            }
        }
    );
    
    /**
     * AppLoader is a development utility that first scans files for interdependencies
     * and then adds them to the dom by injecting script tags. The advantage of
     * doing this is that the browser should be able to reliably detect the
     * location of errors in individual files, prior to any compression that
     * may be performed before deployment to production servers.
     * 
     * @constructor
     * @extends {ie.ondevice.objectkit.utility.compiler.Compiler}
     */
    function AppLoader () 
    {
        Compiler.call(this);
    };

Runtime.declare("ie.ondevice.objectkit.utility.apploader.AppLoader",AppLoader);

})();